fix: bridge filled sell proceeds for follow-up buy - #317
Conversation
Co-Authored-By: Codex <noreply@openai.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 723550bfc2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| available_buying_power=investable_cash, | ||
| ref_price=ref_price, | ||
| quantity_step=_buy_step_for(market_symbol(symbol)), | ||
| allow_top_up=sell_submitted, |
There was a problem hiding this comment.
Preserve one-share top-ups under the min-notional gate
When this runs through run_strategy, config.min_order_notional_usd defaults to 100, so buy_candidates is still filtered by the pre-top-up target gap before this new allow_top_up path is reached. In the regression scenario added here ($260 target, $200 current value, $100 share), the order notional is a valid one share but the $60 gap is below the runtime min-notional gate, so production skips the candidate while the direct unit test passes only because it omits min_order_notional_usd. The top-up candidate needs to be admitted based on the planned one-share notional, not only the raw gap.
Useful? React with 👍 / 👎.
| investable_cash = max( | ||
| float(execution["investable_cash"]), | ||
| previous_investable_cash + projected_sell_release_value, | ||
| ) |
There was a problem hiding this comment.
Project filled sell proceeds into available cash too
When a confirmed sell fill is bridged but the refreshed snapshot still reports negative liquid_cash, this only raises investable_cash; available_cash stays stale. The existing cash-only guard below still clears buy_candidates on available_cash < 0, so sell-then-buy cycles remain skipped for accounts that started slightly negative even though the fill was confirmed and counted as buying power. Please project the confirmed release into the cash value used by that guard as well.
Useful? React with 👍 / 👎.
| investable_cash = max( | ||
| float(execution["investable_cash"]), | ||
| previous_investable_cash + projected_sell_release_value, | ||
| ) |
There was a problem hiding this comment.
Respect reserved cash when projecting sell fills
For strategies with a reserved-cash floor or ratio, execution["investable_cash"] is already net of that reserve, but this projection adds the full filled sell value to the previous net amount. If the account had little investable cash before the sell (for example because a $1,500 reserve consumed it), a confirmed $2,000 sell gets treated as $2,000 investable instead of roughly $500, so the follow-up buy can consume cash that the strategy explicitly reserved. Recompute the projected investable cash from projected liquid cash minus reserved_cash, or otherwise cap it by the same reserve policy.
Useful? React with 👍 / 👎.
Summary
fetch_order_statusthrough the rebalance runtime and add regression coverageVerification
python3 -m pytest -q tests/test_rebalance_service.py -k "sell_fill_bridge_can_top_up_existing_position_after_stale_refresh"python3 -m pytest -q tests/test_runtime_composer.pyNotes
tests/test_rebalance_service.pystill has two pre-existing failures onorigin/mainunrelated to this patch (verified in a cleanorigin/mainworktree).